/**
 * @file websocketclient.cpp
 * @brief WebSocket客户端类实现文件
 *
 * 实现WebSocket客户端的所有功能，包括：
 * - 连接管理和状态控制
 * - 消息的发送和接收处理
 * - 自动重连和心跳机制
 * - 游戏专用消息协议处理
 * - 错误处理和日志记录
 */

#include "../include/websocketclient.h"
#include "../include/config.h"
#include <QDebug>               // 调试输出
#include <QDateTime>            // 时间处理
#include <QUuid>                // UUID生成
#include <QThread>              // 线程处理
#include <QCoreApplication>     // 应用程序信息

#include <QGuiApplication>
#include <QScreen>
#include <QSysInfo>

/**
 * @brief WebSocketClient构造函数
 * @param parent 父对象指针
 *
 * 初始化WebSocket客户端的所有组件：
 * 1. 创建WebSocket对象和定时器
 * 2. 设置默认配置参数
 * 3. 建立信号槽连接
 */
WebSocketClient::WebSocketClient(QObject *parent)
    : QObject(parent)
    , m_webSocket(nullptr)
    , m_connectionState(Disconnected)
    , m_heartbeatTimer(new QTimer(this))
    , m_reconnectTimer(new QTimer(this))
    , m_messageQueueTimer(new QTimer(this))
    , m_autoReconnect(true)
    , m_reconnectAttempts(0)
    , m_queueEnabled(true)
    , m_connectTime(0)
    , m_lastHeartbeat(0)
    , m_messagesSent(0)
    , m_messagesReceived(0)
{
    // === 初始化定时器 ===
    setupTimers();

    // === 创建WebSocket对象 ===
    setupWebSocket();

    qDebug() << "WebSocketClient initialized";
}

/**
 * @brief WebSocketClient析构函数
 *
 * 清理资源，确保连接正确关闭
 */
WebSocketClient::~WebSocketClient()
{
    if (m_webSocket && m_webSocket->state() == QAbstractSocket::ConnectedState) {
        m_webSocket->close();
    }
    qDebug() << "WebSocketClient destroyed";
}

/**
 * @brief 设置WebSocket对象
 *
 * 创建WebSocket对象并建立信号槽连接
 */
void WebSocketClient::setupWebSocket()
{
    if (m_webSocket) {
        m_webSocket->deleteLater();
    }

    m_webSocket = new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this);

    // === 建立WebSocket信号槽连接 ===
    connect(m_webSocket, &QWebSocket::connected,
            this, &WebSocketClient::onWebSocketConnected);
    connect(m_webSocket, &QWebSocket::disconnected,
            this, &WebSocketClient::onWebSocketDisconnected);
    connect(m_webSocket, &QWebSocket::errorOccurred,
            this, &WebSocketClient::onWebSocketError);
    connect(m_webSocket, &QWebSocket::textMessageReceived,
            this, &WebSocketClient::onWebSocketTextMessageReceived);
    connect(m_webSocket, &QWebSocket::binaryMessageReceived,
            this, &WebSocketClient::onWebSocketBinaryMessageReceived);
    connect(m_webSocket, &QWebSocket::sslErrors,
            this, &WebSocketClient::onWebSocketSslErrors);
}

/**
 * @brief 设置定时器
 *
 * 配置心跳、重连和消息队列定时器
 */
void WebSocketClient::setupTimers()
{
    // === 心跳定时器 ===
    m_heartbeatTimer->setSingleShot(false);
    m_heartbeatTimer->setInterval(30000); // 默认30秒
    connect(m_heartbeatTimer, &QTimer::timeout,
            this, &WebSocketClient::onHeartbeatTimer);

    // === 重连定时器 ===
    m_reconnectTimer->setSingleShot(true);
    m_reconnectTimer->setInterval(5000); // 默认5秒
    connect(m_reconnectTimer, &QTimer::timeout,
            this, &WebSocketClient::onReconnectTimer);

    // === 消息队列定时器 ===
    m_messageQueueTimer->setSingleShot(false);
    m_messageQueueTimer->setInterval(100); // 100ms处理一次队列
    connect(m_messageQueueTimer, &QTimer::timeout,
            this, &WebSocketClient::onMessageQueueTimer);
}

/**
 * @brief 连接到游戏服务器
 * @param config 连接配置
 * @return 是否成功开始连接
 */
bool WebSocketClient::connectToServer(const ConnectionConfig &config)
{
    // === 严格检查连接状态，避免重复连接 ===
    if (m_connectionState == Connected) {
        qWarning() << "WebSocketClient: 已经连接，忽略重复连接请求";
        return true;  // 已连接，返回成功
    }

    if (m_connectionState == Connecting) {
        qWarning() << "WebSocketClient: 正在连接中，忽略重复连接请求";
        return false;  // 正在连接，返回失败
    }

    // === 保存配置 ===
    m_config = config;
    m_reconnectAttempts = 0;  // 只在首次连接时重置

    qDebug() << "WebSocketClient: 开始新的连接，状态:" << m_connectionState;

    return doConnect();
}

/**
 * @brief 执行实际的连接操作（不重置重连计数器）
 * @return 是否成功开始连接
 */
bool WebSocketClient::doConnect()
{
    if (m_connectionState == Connected || m_connectionState == Connecting) {
        qWarning() << "Already connected or connecting";
        return false;
    }

    // === 构建连接URL ===
    QUrl url(m_config.serverUrl);
    if (!url.isValid()) {
        qWarning() << "Invalid server URL:" << m_config.serverUrl;
        emit connectionError("Invalid server URL");
        return false;
    }

    // === 添加查询参数 ===
    QUrlQuery query;
    query.addQueryItem("token", m_config.gameToken);
    query.addQueryItem("player_id", m_config.playerId);
    query.addQueryItem("protocol_version", "1.0");
    query.addQueryItem("client_type", "qt6");
    url.setQuery(query);

    qDebug() << "Connecting to:" << url.toString(QUrl::RemoveQuery);

    // === 设置连接状态 ===
    setState(Connecting);

    // === 配置WebSocket ===
    if (m_config.enableSSL) {
        QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
        m_webSocket->setSslConfiguration(sslConfig);
    }

    // === 开始连接 ===
    // 根据实际握手信息，服务器支持Authorization头和协议
    QNetworkRequest request(url);

    // === 添加必需的Authorization头 ===
    if (!m_config.gameToken.isEmpty()) {
        request.setRawHeader("Authorization", QString("Bearer %1").arg(m_config.gameToken).toUtf8());
    }

    // === 添加协议支持（根据API文档要求） ===
    if (!m_config.protocols.isEmpty()) {
        request.setRawHeader("Sec-WebSocket-Protocol", m_config.protocols.join(", ").toUtf8());
    } else {
        // 根据API文档，使用snake-game-v1协议
        request.setRawHeader("Sec-WebSocket-Protocol", "snake-game-v1");
    }

    // === 添加其他必需头 ===
    request.setRawHeader("User-Agent", "Qt6-SnakeGame-Client/1.0");

    qDebug() << "WebSocketClient: 使用Authorization头连接WebSocket";
    qDebug() << "  URL:" << url.toString();
    qDebug() << "  Authorization: Bearer [token]";
    qDebug() << "  Protocols:" << m_config.protocols.join(", ");

    m_webSocket->open(request);

    return true;
}

/**
 * @brief 断开连接
 * @param reason 断开原因
 */
void WebSocketClient::disconnectFromServer(const QString &reason)
{
    qDebug() << "Disconnecting from server, reason:" << reason;

    // === 停止所有定时器 ===
    m_heartbeatTimer->stop();
    m_reconnectTimer->stop();
    m_messageQueueTimer->stop();

    // === 设置状态 ===
    setState(Disconnected);

    // === 关闭WebSocket连接 ===
    if (m_webSocket && m_webSocket->state() == QAbstractSocket::ConnectedState) {
        m_webSocket->close();
    }

    // === 清理状态 ===
    m_sessionId.clear();
    m_currentRoomId.clear();

    emit disconnected(reason);
}

/**
 * @brief 设置连接状态
 * @param state 新状态
 */
void WebSocketClient::setState(ConnectionState state)
{
    if (m_connectionState != state) {
        ConnectionState oldState = m_connectionState;
        m_connectionState = state;

        qDebug() << "Connection state changed from" << oldState << "to" << state;
        emit connectionStateChanged(state);
    }
}

/**
 * @brief 发送JSON消息
 * @param message JSON消息对象
 * @return 是否成功发送
 */
bool WebSocketClient::sendMessage(const QJsonObject &message)
{
    if (m_connectionState != Connected && m_connectionState != Authenticated) {
        if (m_queueEnabled) {
            queueMessage(message);
            return true;
        } else {
            qWarning() << "Cannot send message: not connected";
            return false;
        }
    }

    // === 添加消息ID和时间戳 ===
    QJsonObject messageWithMeta = message;
    messageWithMeta["message_id"] = generateMessageId();
    messageWithMeta["timestamp"] = QDateTime::currentMSecsSinceEpoch();

    // === 转换为JSON字符串 ===
    QJsonDocument doc(messageWithMeta);
    QString jsonString = doc.toJson(QJsonDocument::Compact);

    // === 发送消息 ===
    qint64 bytesSent = m_webSocket->sendTextMessage(jsonString);
    if (bytesSent > 0) {
        m_messagesSent++;
        logMessage("SENT", messageWithMeta);
        return true;
    } else {
        qWarning() << "Failed to send message";
        return false;
    }
}

/**
 * @brief 发送文本消息
 * @param message 文本消息
 * @return 是否成功发送
 */
bool WebSocketClient::sendTextMessage(const QString &message)
{
    QJsonObject jsonMessage;
    jsonMessage["type"] = "text";
    jsonMessage["content"] = message;
    return sendMessage(jsonMessage);
}

/**
 * @brief WebSocket连接成功处理
 */
void WebSocketClient::onWebSocketConnected()
{
    qDebug() << "WebSocket connected successfully";

    // === 更新连接状态 ===
    setState(Connected);
    m_connectTime = QDateTime::currentMSecsSinceEpoch();
    m_reconnectAttempts = 0;

    // === 根据API文档，连接成功后等待欢迎消息，不立即发送认证 ===
    qDebug() << "WebSocketClient: 连接成功，等待服务器欢迎消息...";

    // === 启动心跳定时器 ===
    m_heartbeatTimer->setInterval(m_config.heartbeatInterval);
    m_heartbeatTimer->start();

    // === 启动消息队列处理 ===
    if (m_queueEnabled) {
        m_messageQueueTimer->start();
    }

    emit connected();
}

/**
 * @brief WebSocket断开连接处理
 */
void WebSocketClient::onWebSocketDisconnected()
{
    qDebug() << "WebSocket disconnected";

    // === 停止定时器 ===
    m_heartbeatTimer->stop();
    m_messageQueueTimer->stop();

    // === 更新状态 ===
    ConnectionState oldState = m_connectionState;
    setState(Disconnected);

    // === 暂时禁用自动重连，避免无限循环 ===
    qDebug() << "WebSocket断开连接，不进行自动重连";
    emit disconnected("Connection lost");
}

/**
 * @brief WebSocket错误处理
 * @param error 错误类型
 */
void WebSocketClient::onWebSocketError(QAbstractSocket::SocketError error)
{
    QString errorString = m_webSocket->errorString();
    qWarning() << "WebSocket error:" << error << errorString;

    setState(Error);
    emit connectionError(errorString);

    // === 暂时禁用自动重连，避免无限循环 ===
    qDebug() << "WebSocket错误，不进行自动重连";
}

/**
 * @brief 处理接收到的文本消息
 * @param message 接收到的消息
 */
void WebSocketClient::onWebSocketTextMessageReceived(const QString &message)
{
    m_messagesReceived++;

    // === 解析JSON消息 ===
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &error);

    if (error.error != QJsonParseError::NoError) {
        qWarning() << "Failed to parse JSON message:" << error.errorString();
        return;
    }

    QJsonObject messageObj = doc.object();
    logMessage("RECEIVED", messageObj);

    // === 处理消息 ===
    processMessage(messageObj);
}

/**
 * @brief 处理接收到的二进制消息
 * @param data 二进制数据
 */
void WebSocketClient::onWebSocketBinaryMessageReceived(const QByteArray &data)
{
    qDebug() << "Received binary message, size:" << data.size();
    // 目前不处理二进制消息，可以根据需要扩展
}

/**
 * @brief 处理SSL错误
 * @param errors SSL错误列表
 */
void WebSocketClient::onWebSocketSslErrors(const QList<QSslError> &errors)
{
    qWarning() << "SSL errors occurred:";
    for (const QSslError &error : errors) {
        qWarning() << "  " << error.errorString();
    }

    // 在生产环境中应该更严格地处理SSL错误
    // 这里为了开发方便，忽略SSL错误
    m_webSocket->ignoreSslErrors();
}

/**
 * @brief 心跳定时器处理
 */
void WebSocketClient::onHeartbeatTimer()
{
    if (m_connectionState == Authenticated) {
        sendHeartbeat();
    }
}

/**
 * @brief 重连定时器处理
 */
void WebSocketClient::onReconnectTimer()
{
    // === 完全禁用重连机制，避免无限循环 ===
    qDebug() << "WebSocketClient: 重连定时器触发，但重连已禁用";
    qWarning() << "WebSocketClient: 重连机制已禁用，停止重连尝试";
    emit connectionError("连接已断开，重连机制已禁用");
}

/**
 * @brief 消息队列定时器处理
 */
void WebSocketClient::onMessageQueueTimer()
{
    processMessageQueue();
}

/**
 * @brief 处理消息
 * @param message JSON消息对象
 */
void WebSocketClient::processMessage(const QJsonObject &message)
{
    QString type = message["type"].toString();

    if (type == "welcome") {  // 根据API文档添加欢迎消息处理
        handleWelcomeMessage(message);
    } else if (type == "authentication_result") {  // 根据API文档修改
        handleAuthenticationResponse(message);
    } else if (type == "game_state_update") {
        // === 根据API文档和日志分析，传递完整的消息对象 ===
        // 让updateGameState方法自己处理data字段的解析
        emit gameStateUpdated(message);
    } else if (type == "player_joined") {
        QString playerId = message["player_id"].toString();
        QString playerName = message["player_name"].toString();
        emit playerJoined(playerId, playerName);
    } else if (type == "player_left") {
        QString playerId = message["player_id"].toString();
        emit playerLeft(playerId);
    } else if (type == "room_created") {
        if (message["success"].toBool()) {
            QString roomId = message["room_id"].toString();
            QJsonObject roomInfo = message["room_config"].toObject();  // 根据实际消息结构
            emit roomCreated(roomId, roomInfo);
        }
    } else if (type == "join_room_response") {
        if (message["success"].toBool()) {
            QString roomId = message["room_id"].toString();
            m_currentRoomId = roomId;
            emit roomJoined(roomId);
        }
    } else if (type == "chat_message") {
        QString senderId = message["sender_id"].toString();
        QString senderName = message["sender_name"].toString();
        QString content = message["message"].toString();
        emit chatMessageReceived(senderId, senderName, content);
    } else if (type == "game_started") {
        emit gameStarted();
    } else if (type == "game_ended") {
        QJsonObject results = message["results"].toObject();
        emit gameEnded(results);
    } else if (type == "heartbeat_response") {
        m_lastHeartbeat = QDateTime::currentMSecsSinceEpoch();
    } else if (type == "ping") {
        // 根据API文档处理ping消息
        handlePingMessage(message);
    } else if (type == "heartbeat") {
        // Qt6优化心跳，回 qt6_heartbeat
        QJsonObject hb;
        hb["type"] = "qt6_heartbeat";
        hb["client_time"] = QDateTime::currentMSecsSinceEpoch();
        if (message.contains("timestamp")) hb["server_time"] = message["timestamp"];
        if (message.contains("data") && message["data"].toObject().contains("server_time")) hb["server_time"] = message["data"].toObject()["server_time"];
        sendMessage(hb);
    } else if (type == "error") {
        QString errorCode = message["error_code"].toString();
        QString errorMessage = message["error_message"].toString();

        // === 区分连接错误和游戏业务错误 ===
        if (errorCode == "AUTHENTICATION_FAILED" ||
            errorCode == "CONNECTION_REFUSED" ||
            errorCode == "INVALID_TOKEN" ||
            errorCode == "SESSION_EXPIRED") {
            // 这些是真正的连接错误
            emit connectionError(errorMessage);
        } else {
            // 其他错误是游戏业务错误，不应该触发连接失败
            qDebug() << "WebSocketClient: 收到游戏业务错误:" << errorCode << "-" << errorMessage;
            emit gameError(errorCode, errorMessage);
        }
    }

    // === 发送原始消息信号给NetworkThread处理 ===
    // 所有消息都需要发送给NetworkThread进行统一处理，包括房间管理消息
    emit messageReceived(message);
}

/**
 * @brief 处理欢迎消息
 * @param message 欢迎消息
 */
void WebSocketClient::handleWelcomeMessage(const QJsonObject &message)
{
    qDebug() << "WebSocketClient: 收到欢迎消息";

    QString playerId = message["player_id"].toString();
    QJsonObject serverInfo = message["server_info"].toObject();
    qint64 timestamp = message["timestamp"].toVariant().toLongLong();

    qDebug() << "  临时player_id:" << playerId;
    qDebug() << "  服务器名称:" << serverInfo["name"].toString();
    qDebug() << "  服务器版本:" << serverInfo["version"].toString();
    qDebug() << "  服务器特性:" << serverInfo["features"].toArray();
    qDebug() << "  时间戳:" << timestamp;

    // === 保存临时玩家ID ===
    m_temporaryPlayerId = playerId;

    // === 根据API文档，收到欢迎消息后发送认证消息 ===
    qDebug() << "WebSocketClient: 收到欢迎消息，现在发送认证消息";
    // 使用sessionToken进行消息认证，而不是gameToken（用于连接头）
    QString authToken = m_config.sessionToken.isEmpty() ? m_config.gameToken : m_config.sessionToken;
    sendAuthentication(authToken, m_config.playerId);

    // === 发出欢迎消息信号 ===
    emit welcomeMessageReceived(message);

    // === 发送Qt6客户端信息，便于服务器下发server_config（心跳等） ===
    QJsonObject clientInfo;
    clientInfo["type"] = "qt6_client_info";
    QJsonObject info;
    info["qt_version"] = QT_VERSION_STR;
    info["client_version"] = "1.0.0";
    info["platform"] = QSysInfo::prettyProductName();
    info["supports_compression"] = true;
    info["preferred_fps"] = 60;
    info["screen_resolution"] = QString("%1x%2").arg(QGuiApplication::primaryScreen()->size().width()).arg(QGuiApplication::primaryScreen()->size().height());
    clientInfo["client_info"] = info;
    sendMessage(clientInfo);
}

/**
 * @brief 处理认证响应
 * @param response 认证响应消息
 */
void WebSocketClient::handleAuthenticationResponse(const QJsonObject &response)
{
    qDebug() << "WebSocketClient: 处理认证响应（根据API文档格式）";
    qDebug() << "  响应内容:" << QJsonDocument(response).toJson(QJsonDocument::Compact);

    bool success = response["success"].toBool();
    if (success) {
        setState(Authenticated);

        // === 根据API文档解析认证成功响应 ===
        QString playerId = response["player_id"].toString();
        QString userId = response["user_id"].toString();
        QString message = response["message"].toString();
        bool qt6Optimized = response["qt6_optimized"].toBool();

        qDebug() << "WebSocketClient: 认证成功";
        qDebug() << "  player_id:" << playerId;
        qDebug() << "  user_id:" << userId;
        qDebug() << "  message:" << message;
        qDebug() << "  qt6_optimized:" << qt6Optimized;

        // === 构建玩家信息对象 ===
        QJsonObject playerInfo;
        playerInfo["player_id"] = playerId;
        playerInfo["user_id"] = userId;
        playerInfo["qt6_optimized"] = qt6Optimized;
        playerInfo["message"] = message;

        emit authenticated(playerInfo);
    } else {
        QString errorCode = response["error_code"].toString();
        QString errorMessage = response["message"].toString();

        qWarning() << "WebSocketClient: 认证失败";
        qWarning() << "  error_code:" << errorCode;
        qWarning() << "  message:" << errorMessage;

        emit authenticationFailed(QString("%1: %2").arg(errorCode, errorMessage));
    }
}

/**
 * @brief 发送认证消息
 * @param token 游戏令牌
 * @param playerId 玩家ID
 */
void WebSocketClient::sendAuthentication(const QString &token, const QString &playerId)
{
    qDebug() << "WebSocketClient: 发送认证消息（根据API文档格式）";
    qDebug() << "  token长度:" << token.length();
    qDebug() << "  playerId:" << playerId;

    // === 根据API文档构建认证消息 ===
    QJsonObject authMessage;
    authMessage["type"] = "authenticate";
    authMessage["token"] = token;  // 根据API文档第64行示例，使用token字段

    // === 直接发送认证消息，不添加额外字段 ===
    QJsonDocument doc(authMessage);
    QString jsonString = doc.toJson(QJsonDocument::Compact);

    qint64 bytesSent = m_webSocket->sendTextMessage(jsonString);
    if (bytesSent > 0) {
        m_messagesSent++;
        logMessage("SENT", authMessage);
        qDebug() << "WebSocketClient: 认证消息已发送";
    } else {
        qWarning() << "WebSocketClient: 认证消息发送失败";
    }
    qDebug() << "WebSocketClient: 认证消息已发送";
}

/**
 * @brief 创建游戏房间
 * @param roomName 房间名称
 * @param config 房间配置
 */
void WebSocketClient::createRoom(const QString &roomName, const QJsonObject &config)
{
    if (m_connectionState != Authenticated) {
        qWarning() << "Cannot create room: not authenticated";
        return;
    }

    QJsonObject message;
    message["type"] = "create_room";
    message["room_name"] = roomName;
    message["max_players"] = config.contains("max_players") ? config["max_players"].toInt() : 4;
    message["game_mode"] = config.contains("game_mode") ? config["game_mode"].toInt() : 1;
    message["map_width"] = config.contains("map_width") ? config["map_width"].toInt() : 40;
    message["map_height"] = config.contains("map_height") ? config["map_height"].toInt() : 30;
    message["game_speed_ms"] = config.contains("game_speed_ms") ? config["game_speed_ms"].toInt() : 100;
    message["enable_walls"] = config.contains("enable_walls") ? config["enable_walls"].toBool() : true;
    message["enable_special_foods"] = config.contains("enable_special_foods") ? config["enable_special_foods"].toBool() : false;

    sendMessage(message);
}

/**
 * @brief 加入游戏房间
 * @param roomId 房间ID
 */
void WebSocketClient::joinRoom(const QString &roomId)
{
    if (m_connectionState != Authenticated) {
        qWarning() << "Cannot join room: not authenticated";
        return;
    }

    QJsonObject message;
    message["type"] = "join_room";
    message["room_id"] = roomId;

    sendMessage(message);
}

/**
 * @brief 离开游戏房间
 */
void WebSocketClient::leaveRoom()
{
    if (m_connectionState != Authenticated || m_currentRoomId.isEmpty()) {
        qWarning() << "Cannot leave room: not in a room";
        return;
    }

    QJsonObject message;
    message["type"] = "leave_room";
    message["room_id"] = m_currentRoomId;

    sendMessage(message);
    m_currentRoomId.clear();
}

/**
 * @brief 改变移动方向
 * @param direction 方向（0=上，1=右，2=下，3=左）
 */
void WebSocketClient::changeDirection(int direction)
{
    if (m_connectionState != Authenticated) {
        qWarning() << "Cannot change direction: not authenticated";
        return;
    }

    QJsonObject message;
    message["type"] = "change_direction";
    message["direction"] = direction;

    sendMessage(message);
}

/**
 * @brief 发送聊天消息
 * @param message 聊天内容
 */
void WebSocketClient::sendChatMessage(const QString &message)
{
    if (m_connectionState != Authenticated || m_currentRoomId.isEmpty()) {
        qWarning() << "Cannot send chat message: not in a room";
        return;
    }

    QJsonObject chatMessage;
    chatMessage["type"] = "chat_message";
    chatMessage["room_id"] = m_currentRoomId;
    chatMessage["message"] = message;

    sendMessage(chatMessage);
}

/**
 * @brief 设置心跳间隔
 * @param interval 间隔时间（毫秒）
 */
void WebSocketClient::setHeartbeatInterval(int interval)
{
    m_config.heartbeatInterval = interval;
    if (m_heartbeatTimer->isActive()) {
        m_heartbeatTimer->setInterval(interval);
    }
}

/**
 * @brief 获取连接统计信息
 * @return 统计信息JSON对象
 */
QJsonObject WebSocketClient::getConnectionStats() const
{
    QJsonObject stats;
    stats["connection_state"] = static_cast<int>(m_connectionState);
    stats["connect_time"] = m_connectTime;
    stats["last_heartbeat"] = m_lastHeartbeat;
    stats["messages_sent"] = m_messagesSent;
    stats["messages_received"] = m_messagesReceived;
    stats["reconnect_attempts"] = m_reconnectAttempts;
    stats["session_id"] = m_sessionId;
    stats["current_room_id"] = m_currentRoomId;

    if (m_connectTime > 0) {
        qint64 uptime = QDateTime::currentMSecsSinceEpoch() - m_connectTime;
        stats["uptime_ms"] = uptime;
    }

    return stats;
}

/**
 * @brief 发送心跳消息
 */
void WebSocketClient::sendHeartbeat()
{
    QJsonObject heartbeat;
    heartbeat["type"] = "heartbeat";
    heartbeat["timestamp"] = QDateTime::currentMSecsSinceEpoch();
    heartbeat["session_id"] = m_sessionId;

    sendMessage(heartbeat);
}

/**
 * @brief 开始重连
 */
void WebSocketClient::startReconnect()
{
    // === 完全禁用重连机制 ===
    qDebug() << "WebSocketClient: startReconnect被调用，但重连机制已禁用";
    qWarning() << "WebSocketClient: 重连机制已禁用，不会启动重连定时器";
}

/**
 * @brief 处理消息队列
 */
void WebSocketClient::processMessageQueue()
{
    if (m_connectionState != Authenticated) {
        return;
    }

    QMutexLocker locker(&m_queueMutex);

    int processed = 0;
    const int maxBatch = 10; // 每次最多处理10条消息

    while (!m_messageQueue.isEmpty() && processed < maxBatch) {
        QJsonObject message = m_messageQueue.dequeue();

        // === 添加消息ID和时间戳 ===
        message["message_id"] = generateMessageId();
        message["timestamp"] = QDateTime::currentMSecsSinceEpoch();

        // === 转换为JSON字符串 ===
        QJsonDocument doc(message);
        QString jsonString = doc.toJson(QJsonDocument::Compact);

        // === 发送消息 ===
        qint64 bytesSent = m_webSocket->sendTextMessage(jsonString);
        if (bytesSent > 0) {
            m_messagesSent++;
            logMessage("SENT_QUEUED", message);
            processed++;
        } else {
            // 发送失败，重新放回队列
            m_messageQueue.prepend(message);
            break;
        }
    }
}

/**
 * @brief 将消息加入队列
 * @param message 消息对象
 */
void WebSocketClient::queueMessage(const QJsonObject &message)
{
    QMutexLocker locker(&m_queueMutex);

    // === 检查队列大小限制 ===
    const int maxQueueSize = 100;
    if (m_messageQueue.size() >= maxQueueSize) {
        qWarning() << "Message queue full, dropping oldest message";
        m_messageQueue.dequeue();
    }

    m_messageQueue.enqueue(message);
    qDebug() << "Message queued, queue size:" << m_messageQueue.size();
}

/**
 * @brief 生成消息ID
 * @return 唯一消息ID
 */
QString WebSocketClient::generateMessageId() const
{
    return QUuid::createUuid().toString(QUuid::WithoutBraces);
}

/**
 * @brief 记录消息日志
 * @param direction 消息方向（SENT/RECEIVED）
 * @param message 消息对象
 */
void WebSocketClient::logMessage(const QString &direction, const QJsonObject &message)
{
    QString type = message["type"].toString();
    QString messageId = message["message_id"].toString();

    // === 过滤心跳消息的日志 ===
    if (type == "heartbeat" || type == "heartbeat_response") {
        return;
    }

    // === 降噪：禁止打印完整JSON，避免UI阻塞 ===
    static int logCount = 0;
    logCount++;

    // 对于game_state_update，只每60条打印一次摘要
    if (type == "game_state_update") {
        if (logCount % 60 == 1) {
            QJsonObject data = message["data"].toObject();
            QJsonArray snakes = data["snakes"].toArray();
            QJsonArray foods = data["foods"].toArray();
            qDebug() << QString("WebSocket收到游戏状态: snakes=%1, foods=%2 (每60帧摘要)")
                        .arg(snakes.size()).arg(foods.size());
        }
    } else if (type == "error") {
        // 错误消息总是打印
        qWarning() << "WebSocketClient: 收到游戏业务错误:" << message;
    } else {
        // 其他消息只打印类型，不打印完整JSON
        qDebug() << QString("WebSocket收到: %1").arg(type);
    }
}

/**
 * @brief 处理ping消息
 * @param message ping消息
 */
void WebSocketClient::handlePingMessage(const QJsonObject &message)
{
    qDebug() << "WebSocketClient: 收到服务器ping消息";

    // 根据API文档，ping消息格式：
    // {"server_status":"running","timestamp":1755094923756,"type":"ping"}

    QString serverStatus = message["server_status"].toString();
    qint64 serverTimestamp = message["timestamp"].toVariant().toLongLong();

    qDebug() << "  服务器状态:" << serverStatus;
    qDebug() << "  服务器时间戳:" << serverTimestamp;

    // 主动发送pong以保持会话活跃
    QJsonObject pong;
    pong["type"] = "pong";
    pong["timestamp"] = QDateTime::currentMSecsSinceEpoch();
    sendMessage(pong);
}
